from xml.dom import minidom
from os.path import basename
from cgi import escape as html_escape
from xml.sax.saxutils import unescape as xml_unescape

doctype = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'''

class HtmlParser:
    '''
    Transforms symbide xml to valid html.
    '''
    
    def transform(self, DOM, stylePath):
        html = minidom.Element('html')
        
        html.appendChild(self.head(DOM, stylePath))
        html.appendChild(self.worksheet(DOM))
        
        return doctype + '\n' + html.toxml()
    
    def head(self, DOM, stylePath):
        '''
        Creates the head.
        '''
        
        head = minidom.Element('head')
        title = minidom.Element('title')
        t = DOM.getAttribute('title')
        t_node = minidom.Document().createTextNode(t)
        title.appendChild(t_node)
        css = minidom.Element('link')
        css.setAttribute('rel','stylesheet')
        css.setAttribute('type','text/css')
        css.setAttribute('href',stylePath)
        head.appendChild(title)
        head.appendChild(css)
        return head
    
    def worksheet(self, DOM):
        body = minidom.Element('body')
        for cell in DOM.getElementsByTagName('cell'):
            body.appendChild(self.cell(cell))
            br = minidom.Element('br')
            body.appendChild(br)
        return body
    
    def cell(self, DOM):
        table = minidom.Element('table')
        table.setAttribute('class', 'cell')
        tbody = minidom.Element('tbody')
        table.appendChild(tbody)
        
        DOM_input = DOM.getElementsByTagName('input')[0]
        tbody.appendChild(self.input(DOM_input))
        
        DOM_output = DOM.getElementsByTagName('output')[0]
        tbody.appendChild(self.output(DOM_output))
        return table
        
    def input(self, DOM):
        row = minidom.Element('tr')
        row.setAttribute('class','input')
        column = minidom.Element('td')
        row.appendChild(column)
        pre = minidom.Element('pre')
        column.appendChild(pre)
        for n in DOM.childNodes:
            if n.nodeType==n.TEXT_NODE:
                pre.appendChild(self.text(n))
            elif n.localName=='input':
                pre.appendChild(self.subinput(n))
        return row
    
    def subinput(self, DOM):
        if DOM.hasAttribute('type'):
            type = DOM.getAttribute('type')
        span = minidom.Element('span')
        span.setAttribute('class', 'input%s'%type)
        
        for n in DOM.childNodes:
            if n.nodeType==n.TEXT_NODE:
                span.appendChild(self.text(n))
            elif n.localName=='input':
                span.appendChild(self.subinput(n))
        return span
            
    def output(self, DOM):
        row = minidom.Element('tr')
        row.setAttribute('class','output')
        column = minidom.Element('td')
        row.appendChild(column)
        pre = minidom.Element('pre')
        column.appendChild(pre)
        for n in DOM.childNodes:
            if n.nodeType==n.TEXT_NODE:
                pre.appendChild(self.text(n))
            elif n.localName=='img':
                p = minidom.Element('p')
                p.appendChild(n)
                pre.appendChild(p)
        return row
    
    def text(self, DOM):
        text = DOM.cloneNode(False)
        data = '<span>'+html_escape(xml_unescape(DOM.data))+'</span>'
        return minidom.parseString(data).documentElement.cloneNode(True)